﻿using Yitter.IdGenerator;

namespace Admin.NET.Application.Service;


/// <summary>
/// 一般单据的服务基类
/// </summary>
[ApiDescriptionSettings(KeepName = true)]
public abstract class BaseServiceBill<T> : IDynamicApiController where T : EntityBaseBill, new()
{
    private readonly IServiceScope _serviceScope;
    protected readonly SqlSugarRepository<T> _rep;
    protected readonly BillNoManager _billNoManager; // 创建单号

    public BaseServiceBill(IServiceScopeFactory scopeFactory)
    {
        _serviceScope = scopeFactory.CreateScope();
        _rep = _serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<T>>();
        _billNoManager = _serviceScope.ServiceProvider.GetRequiredService<BillNoManager>();
    }

    public ISugarQueryable<T> Queryable
    {
        get
        {
            return _rep.AsQueryable();
        }
    }

    /// <summary>
    /// 新增
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    protected T AddWithInput(object input)
    {
        // 创建单号
        var inputObject = input.Adapt<T>();
        if (string.IsNullOrEmpty(inputObject.Id))
        {
            inputObject.Id = YitIdHelper.NextId() + "";
        }
        // 新增
        var entity = _rep.InsertReturnEntity(inputObject);

        // 操作记录
        AddOptBill(entity.Id, "新增", "");

        return entity;
    }

    /// <summary>
    /// 通过id查询实体
    /// </summary>
    /// <param name="id"></param>
    protected T SingleById(string id)
    {
        return _rep.InSingle(id);
    }

    /// <summary>
    /// 通过id查询Output
    /// </summary>
    /// <typeparam name="Tout"></typeparam>
    /// <param name="id"></param>
    protected Tout GetById<Tout>(string id)
    {
        var obj = _rep.InSingle(id);
        return obj.Adapt<Tout>();
    }


    /// <summary>
    /// 修改
    /// </summary>
    protected bool UpdateWithInput(object input)
    {
        var inputObject = input.Adapt<T>();
        var isUpdate = _rep.Update(inputObject);
        if (isUpdate)
        {
            // 操作记录
            AddOptBill(inputObject.Id, "修改", input);
        }
        return isUpdate;
    }

    /// <summary>
    /// 作废
    /// </summary>
    protected bool CancelBill(BaseBillCancelInput input)
    {
        var eff = _rep.AsUpdateable(new T() { Id = input.Id, remark = input.remark, danJuZhuangTai = DanJuZhuangTai.已作废 })
              .UpdateColumns(it => new { it.remark, it.UpdateTime, it.UpdateUserId, it.UpdateUserName, it.danJuZhuangTai }).ExecuteCommand();

        if (eff > 0)
        {
            // 操作记录
            AddOptBill(input.Id, "作废", input.remark);
        }
        return eff > 0;
    }

    /// <summary>
    /// 基本的审核功能
    /// </summary>
    protected virtual bool Audit<TAudit>(TAudit input) where TAudit : BaseBillAuditInput, new()
    {
        var eff = _rep.AsUpdateable(new T() { Id = input.Id, remark = input.remark, danJuZhuangTai = DanJuZhuangTai.已生效 })
             .UpdateColumns(it => new { it.remark, it.UpdateTime, it.UpdateUserId, it.UpdateUserName, it.danJuZhuangTai }).ExecuteCommand();

        if (eff > 0)
        {
            // 操作记录
            AddOptBill(input.Id, "审核", input);
        }
        return eff > 0;
    }

    protected bool AddOptBill(string id, string mingCheng, string neiRong)
    {
        var entity = _rep.GetById(id);
        var currentUser = App.User == null || App.User.Identity.IsAuthenticated == false ? UserContext.Default : App.User;

        var repOpt = _rep.ChangeRepository<SqlSugarRepository<OptBill>>();
        return repOpt.Insert(new OptBill()
        {
            entityName = entity.GetType().Name,
            entityId = entity.Id,
            danJuLeiXing = entity.danJuLeiXing,
            caoZuoHouZhuangTai = entity.danJuZhuangTai,

            mingCheng = mingCheng,
            neiRong = neiRong, // 可以把input序列化, 待定

            caoZuoRen = currentUser?.FindFirst(ClaimConst.RealName)?.Value,
            caoZuoRenId = currentUser?.FindFirst(ClaimConst.UserId)?.Value.ToLong() ?? 0,
            caoZuoShiJian = DateTime.Now,
        });
    }

    /// <summary>
    /// 添加操作记录
    /// </summary>
    /// <param name="id">单号</param>
    /// <param name="mingCheng">操作名称</param>
    /// <param name="input">输入</param>
    /// <returns></returns>
    protected bool AddOptBill(string id, string mingCheng, object input)
    {
        return AddOptBill(id, mingCheng, input.ToJson());
    }

}